import {
  PrepComponent,
  PrepStyledComponents,
  PrepCss,
  PrepStorybook,
  PrepDescription,
  PrepGraphicComponent
} from '../../../bin/contracts/PrepFile';

import {
  prepComponent,
  prepStyledComponents,
  prepCss,
  prepStorybook,
  prepDescription,
  prepGraphicComponent
} from '../../../bin/frameworks/filesystem/prepFile';

import { svgData } from '../../../testdata/svg/svg';

describe('Failure cases', () => {
  describe('No input', () => {
    test('prepComponent should throw an error if no argument is provided', () => {
      // @ts-ignore
      expect(() => prepComponent()).toThrow();
    });

    test('prepStyledComponents should throw an error if no argument is provided', () => {
      // @ts-ignore
      expect(() => prepStyledComponents()).toThrow();
    });

    test('prepCss should throw an error if no argument is provided', () => {
      // @ts-ignore
      expect(() => prepCss()).toThrow();
    });

    test('prepStorybook should throw an error if no argument is provided', () => {
      // @ts-ignore
      expect(() => prepStorybook()).toThrow();
    });

    test('prepDescription should throw an error if no argument is provided', () => {
      // @ts-ignore
      expect(() => prepDescription()).toThrow();
    });

    test('prepGraphicComponent should throw an error if no argument is provided', () => {
      // @ts-ignore
      expect(() => prepGraphicComponent()).toThrow();
    });
  });

  describe('Incorrect input', () => {
    test('prepComponent should throw an error if incorrect (empty) input is provided', () => {
      // @ts-ignore
      expect(() => prepComponent({})).toThrow();
    });

    test('prepStyledComponents should throw an error if incomplete input is provided', () => {
      // @ts-ignore
      expect(() => prepStyledComponents({})).toThrow();
    });

    test('prepCss should throw an error if incorrect (empty) input is provided', () => {
      // @ts-ignore
      expect(() => prepCss({})).toThrow();
    });

    test('prepStorybook should throw an error if incorrect (empty) input is provided', () => {
      // @ts-ignore
      expect(() => prepStorybook({})).toThrow();
    });

    test('prepDescription should throw an error if incorrect (empty) input is provided', () => {
      // @ts-ignore
      expect(() => prepDescription({})).toThrow();
    });

    test('prepGraphicComponent should throw an error if incorrect (empty) input is provided', () => {
      // @ts-ignore
      expect(() => prepGraphicComponent({})).toThrow();
    });
  });
});

describe('Success cases', () => {
  // TODO: Test fails inexplicably on Windows?
  test('It should prepare a Component file based on the React template', () => {
    const data = {
      name: 'aaa',
      filePath: 'ComponentName',
      format: 'jsx',
      templates: {
        templatePathReact: 'templates/react'
      },
      text: 'fff',
      extraProps: 'qqq',
      element: 'div'
    };

    const fileContent = `import React from 'react';
import PropTypes from 'prop-types';

import aaaStyled from './aaaStyled';

const aaa = (props) => <aaaStyled qqq {...props}>{props.children ? props.children : \"fff\"}</aaaStyled>;

aaa.propTypes = {};

export default aaa;`;

    const expectedData = { fileContent: fileContent, filePath: 'ComponentName.jsx' };

    expect(prepComponent(data as PrepComponent)).toMatchObject(expectedData);
  });

  test('It should prepare a Styled Components file based on the Styled template', () => {
    const data = {
      name: 'aaa',
      filePath: 'ComponentName',
      format: 'jsx',
      templates: {
        templatePathStyled: 'templates/styled'
      },
      element: 'div'
    };

    const fileContent = `import styled from 'styled-components';

import AaaCss from './AaaCss';

// Extend the below as needed
const AaaStyled = styled.div\`
  \${AaaCss};
\`;

export default AaaStyled;`;

    const expectedData = { fileContent: fileContent, filePath: 'ComponentNameStyled.jsx' };

    expect(prepStyledComponents(data as PrepStyledComponents)).toMatchObject(expectedData);
  });

  test('It should prepare a CSS file based on the CSS template', () => {
    const css = `asdf`;

    const data = {
      name: 'ComponentName',
      filePath: 'ComponentName',
      format: 'js',
      imports: 'asdf',
      file: css
    };

    const fileContent = `// THIS FILE IS AUTO-GENERATED BY FIGMAGIC. DO NOT MAKE EDITS IN THIS FILE! CHANGES WILL GET OVER-WRITTEN BY ANY FURTHER PROCESSING.

asdf
const ComponentNameCss = \`asdf\`;

export default ComponentNameCss;`;

    const expectedData = { fileContent: fileContent, filePath: 'ComponentNameCss.js' };

    expect(prepCss(data as PrepCss)).toMatchObject(expectedData);
  });

  test('It should prepare a Storybook file based on the Storybook template', () => {
    const data = {
      name: 'ComponentName',
      filePath: 'ComponentName',
      format: 'js',
      templates: {
        templatePathStorybook: 'templates/story'
      },
      text: 'Something here'
    };

    const fileContent = `import React from 'react';
import ComponentName from './ComponentName';

import notes from './ComponentName.description.md';

export default { title: 'ComponentName', parameters: { notes } };

export const ComponentNameRegular = () => <ComponentName>Something here</ComponentName>;`;

    const expectedData = { fileContent: fileContent, filePath: 'ComponentName.stories.js' };

    expect(prepStorybook(data as PrepStorybook)).toMatchObject(expectedData);
  });

  test('It should prepare a Markdown description file based on the Markdown template', () => {
    const data = {
      filePath: 'ComponentName',
      file: 'Description here.',
      format: 'md'
    };

    const fileContent = `<!--THIS FILE IS AUTO-GENERATED BY FIGMAGIC. DO NOT MAKE EDITS IN THIS FILE! CHANGES WILL GET OVER-WRITTEN BY ANY FURTHER PROCESSING.-->
Description here.`;

    const expectedData = { fileContent: fileContent, filePath: 'ComponentName.description.md' };

    expect(prepDescription(data as PrepDescription)).toMatchObject(expectedData);
  });

  test('It should prepare a graphic component file based on the React template', () => {
    const data = {
      name: 'aaa',
      filePath: 'ComponentName',
      format: 'tsx',
      templates: {
        templatePathGraphic: 'templates/graphic'
      },
      file: svgData
    };

    const fileContent = `import React from 'react';

const aaa = (): any => <svg width=\"55\" height=\"56\" viewBox=\"0 0 55 56\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M2.11131 28.0662L17.0333 51.499L52.1723 1.43805\" stroke=\"#219653\" stroke-width=\"5\"/>
</svg>

export default aaa;`;

    const expectedData = { fileContent, filePath: 'ComponentName.tsx' };

    expect(prepGraphicComponent(data as PrepGraphicComponent)).toMatchObject(expectedData);
  });
});
